package bll

import (
	"bufio"
	"bytes"
	"encoding/json"
	"fmt"
	"go.uber.org/zap"
	"io"
	"io/ioutil"
	log "maya-service/collector/logger"
	"maya-service/utils"
	"net/http"
	"strings"
)

const (
	apiUrl = "https://api.coze.cn/v3/chat"
	apiKey = "pat_4p43HYBJNIREMJDAMzNqNlojroy0WkKmNY0YDGPxhQFEiu4PtpbKdREcO0vaBSyG" // 替换为您的 API 密钥 	// 替换为您的 Bot ID
)

type Message struct {
	Role        string `json:"role"`
	Content     string `json:"content"`
	ContentType string `json:"content_type"`
	Type        string `json:"type"`
}

type RequestPayload struct {
	BotID              string    `json:"bot_id"`
	UserID             string    `json:"user_id"`
	Stream             bool      `json:"stream"`
	AutoSaveHistory    bool      `json:"auto_save_history"`
	AdditionalMessages []Message `json:"additional_messages"`
}

type ChatResponse struct {
	Content        string `json:"content"`
	ConversationId string `json:"conversation_id"`
}

func CreateConversation(userId string, botId, accessToken string, content string) string {
	type CreateRequestPayload struct {
		Messages []Message         `json:"messages"`
		MetaData map[string]string `json:"meta_data"`
		BotId    string            `json:"bot_id"`
	}
	// 构建请求体
	var payload = CreateRequestPayload{
		Messages: []Message{
			{
				Type:        "question",
				Role:        "user",
				Content:     content,
				ContentType: "text",
			},
		},
		BotId: botId,
	}
	payloadBytes, err := json.Marshal(payload)
	if err != nil {
		log.Error("CreateConversation Error marshaling payload", zap.Any("userId", userId), zap.Any("err", err))
		return ""
	}

	req, err := http.NewRequest("POST", "https://api.coze.cn/v1/conversation/create", bytes.NewBuffer(payloadBytes))
	if err != nil {
		log.Error("CreateConversation Error creating request:", zap.Any("userId", userId), zap.Any("err", err))
		return ""
	}

	// 设置请求头
	req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", accessToken))
	req.Header.Set("Content-Type", "application/json")
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		log.Error("CreateConversation Error sending request", zap.Any("userId", userId), zap.Any("err", err))
		return ""
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		log.Error("CreateConversation Request failed with status", zap.Any("userId", userId), zap.Any("status", resp.Status))
		return ""
	}

	// 读取响应体
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Error("CreateConversation Error reading response body", zap.Any("userId", userId), zap.Any("err", err))
		return ""
	}

	// 解析 JSON 响应
	var response struct {
		Code int `json:"code"`
		Data struct {
			CreatedAt int64  `json:"created_at"`
			ID        string `json:"id"`
			MetaData  struct {
				UUID string `json:"uuid"`
			} `json:"meta_data"`
		} `json:"data"`
		Msg string `json:"msg"`
	}

	err = json.Unmarshal(body, &response)
	if err != nil {
		log.Error("CreateConversation Error unmarshalling response", zap.Any("userId", userId), zap.Any("err", err))
		return ""
	}

	return response.Data.ID
}

func BuildHistoryMessage(content string) (historyMessage []Message) {
	type MessageContent struct {
		Title string `json:"title"`
		Type  int    `json:"type"` // 0 assistant 1 用户
	}

	var chatContent []MessageContent
	err := json.Unmarshal([]byte(content), &chatContent)
	if err != nil {
		return
	}

	for i := 0; i < len(chatContent); i++ {
		role := "user"
		if chatContent[i].Type == 0 {
			role = "assistant"
		}

		messageType := "question"
		if chatContent[i].Type == 0 {
			messageType = "answer"
		}

		historyMessage = append(historyMessage, Message{
			Role:        role,
			Content:     chatContent[i].Title,
			ContentType: "text",
			Type:        messageType,
		})
	}
	return
}

// SendMessage 发送消息
func SendMessage(botId, accessToken string, conversationId string, userId string, message string, historyMessage []Message) (respText string, conversationID string, err error) {

	if botId == "" || accessToken == "" {
		log.Error("SendMessage error", zap.Any("conversationId", conversationId), zap.Any("userId", userId), zap.Any("message", message))
		return "", "", fmt.Errorf("bot id or access token is empty")
	}
	// 构建请求体
	payload := RequestPayload{
		BotID:              botId,
		UserID:             userId,
		Stream:             true,
		AutoSaveHistory:    true,
		AdditionalMessages: []Message{},
	}

	if len(historyMessage) > 0 {
		payload.AdditionalMessages = append(payload.AdditionalMessages, historyMessage...)
	}

	payload.AdditionalMessages = append(payload.AdditionalMessages, Message{
		Type:        "question",
		Role:        "user",
		Content:     message,
		ContentType: "text",
	})

	payloadBytes, err := json.Marshal(payload)
	if err != nil {
		log.Error("SendMessage Error marshaling payload", zap.Any("conversationId", conversationId), zap.Any("userId", userId), zap.Any("message", message), zap.Any("err", err))
		return "", conversationId, err
	}

	log.Info("################ 请求 chat SendMessage ", zap.Any("conversationId", conversationId), zap.Any("userId", userId), zap.Any("content", string(payloadBytes)), zap.Any("botId", botId))

	url := apiUrl
	if conversationId != "" {
		url = fmt.Sprintf("%v?conversation_id=%v", apiUrl, conversationId)
	}
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(payloadBytes))
	if err != nil {
		log.Error("SendMessage Error creating request:", zap.Any("conversationId", conversationId), zap.Any("userId", userId), zap.Any("message", message), zap.Any("err", err))
		return "", conversationId, err
	}

	// 设置请求头
	req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", accessToken))
	req.Header.Set("Content-Type", "application/json")

	// 发送请求
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		log.Error("SendMessage Error sending request", zap.Any("conversationId", conversationId), zap.Any("userId", userId), zap.Any("message", message), zap.Any("err", err))
		return "", conversationId, err
	}
	defer resp.Body.Close()

	log.Info("################ 请求回复内容 ", zap.Any("conversationId", conversationId), zap.Any("userId", userId), zap.Any("message", message), zap.Any("resp", utils.ToJsonString(resp)))

	if resp.StatusCode != http.StatusOK {
		log.Error("SendMessage Request failed with status", zap.Any("conversationId", conversationId), zap.Any("userId", userId), zap.Any("message", message), zap.Any("status", resp.Status))
		return "", conversationId, err
	}

	// 解析流式响应
	isReachPosition := false
	reader := bufio.NewReader(resp.Body)
	var chunks []string
	for {
		line, err := reader.ReadString('\n')
		if err != nil {
			if err == io.EOF {
				break
			}
			fmt.Printf("Error reading response: %v\n", err)
			return "", conversationId, err
		}

		line = strings.TrimSpace(line)
		if strings.Contains(line, "event:conversation.message.completed") {
			isReachPosition = true
		}

		if !isReachPosition {
			continue
		}

		if strings.HasPrefix(line, "data:") {
			// 提取 JSON 数据
			jsonData := strings.TrimPrefix(line, "data:")
			var chatResponse ChatResponse
			err := json.Unmarshal([]byte(jsonData), &chatResponse)
			if err != nil {
				fmt.Printf("Error unmarshaling JSON: %v\n", err)
				continue
			}

			conversationId = chatResponse.ConversationId
			chunks = append(chunks, chatResponse.Content)
			break
		}
	}

	// 合并所有数据块并输出
	if len(chunks) > 0 {
		responseText := strings.Join(chunks, "")
		log.Info("################ 回复 chat SendMessage ", zap.Any("conversationId", conversationId), zap.Any("userId", userId), zap.Any("content", responseText), zap.Any("botId", botId))
		return responseText, conversationId, nil
	} else {
		log.Info("SendMessage No valid response received.", zap.Any("conversationId", conversationId), zap.Any("userId", userId), zap.Any("message", message))
	}

	return "暂时无法理解你的诉求，请重新组织下语言", conversationId, err
}
